package com.intramirror.product.schedule.consumer;

import com.intramirror.core.common.response.Response;
import com.intramirror.product.constant.ProductChangedConstant;
import com.intramirror.product.entity.PriceChangeRule;
import com.intramirror.product.entity.Product;
import com.intramirror.product.entity.SnapshotPriceDetail;
import com.intramirror.product.entity.SnapshotPriceRule;
import com.intramirror.product.service.*;
import com.intramirror.product.vo.ProductChangedVO;
import com.intramirror.utils.transform.JsonTransformUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 123 on 2018/5/25.
 */
@RestController
@RequestMapping("/price")
public class CalculatePrdPrePriceConsumer implements IProductConsumer {
    private static final Logger LOGGER = LoggerFactory.getLogger(CalculatePrdPrePriceConsumer.class);

    public FacilityService facilityService;

    CalculatePrdPrePriceConsumer(FacilityService facilityService) {
        this.facilityService = facilityService;
    }

    @Override
    public void process(String message) {
        LOGGER.info("CalculatePrdPrePriceConsumer process start to run.");
        //接收到商品更新的消息
        LOGGER.info("CalculatePrdPrePriceConsumer: dispatch message:{}", message);
        ProductChangedVO ProductChangedVO = JsonTransformUtil.readValue(message, ProductChangedVO.class);
        if (ProductChangedVO.getProduct_id() == null || ProductChangedVO.getType() == null) {
            LOGGER.error("CalculatePrdPrePriceConsumer: params validate error:{}", message);
            return;
        }

        if (ProductChangedVO.getType() == ProductChangedConstant.PRODUCT_UPDATE_BY_JOB_TYPE_PRICERULE) {
            //重新计算所有snapshot价格
            Map<String, Object> discountMap = dealPreBoutique2ImDiscount(ProductChangedVO.getProduct_id());
            LOGGER.info(
                    "==Jian== boutique_discount is [" + discountMap.get("boutique_discount").toString() + "], im_discount is [" + discountMap.get("im_discount")
                            .toString() + "], im_price_algorithm_id is [" + discountMap.get("im_price_algorithm_id").toString() + "], price_change_rule_id is ["
                            + discountMap.get("price_change_rule_id").toString() + "]");
        }
    }

    @GetMapping("/product/{productId}")
    public Response getProductDiscountById(@PathVariable("productId") Long productId) {
        return Response.status(1).data(dealPreBoutique2ImDiscount(productId));
    }

    public Map<String, Object> dealPreBoutique2ImDiscount(Long productId) {
        IProductService productService = facilityService.getProductService();
        Product product = productService.selectByPrimaryKey(productId);

        if (product == null) {
            LOGGER.error("CalculatePrdPrePriceConsumer: product is not exists. productId={}", productId);
            return null;
        }

        Map<String, Object> discountMap = setDefaultDiscount();
        Map<String, Object> param = setParam(product);

        getPreBoutiqueDiscount(param, discountMap);
        getPreImDiscount(product, discountMap);

        setIm2BoutiquePrice(product, discountMap);
        return discountMap;
    }

    private void setIm2BoutiquePrice(Product product, Map<String, Object> param) {
        IPriceChangeRuleService pcrService = facilityService.getPriceChangeRuleService();

        Long priceChangeRuleId = Long.parseLong(param.get("price_change_rule_id").toString());
        Long imPriceAlgorithmId = Long.parseLong(param.get("im_price_algorithm_id").toString());
        BigDecimal boutiqueDiscount = new BigDecimal(param.get("boutique_discount").toString());
        BigDecimal boutiquePrice = product.getMaxRetailPrice().multiply(boutiqueDiscount).divide(new BigDecimal(122), 2, BigDecimal.ROUND_HALF_UP);
        BigDecimal imDiscount = new BigDecimal(param.get("im_discount").toString());
        BigDecimal imPrice = product.getMaxRetailPrice().multiply(imDiscount).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
        Long snapshotPriceRuleId = -1L;

        List<SnapshotPriceRule> listSnapshotPriceRule = pcrService.selectByPriceChangeRuleId(priceChangeRuleId);
        if (listSnapshotPriceRule != null && listSnapshotPriceRule.size() > 0) {
            SnapshotPriceRule spr = listSnapshotPriceRule.get(0);
            snapshotPriceRuleId = spr.getSnapshotPriceRuleId();
        }

        Map<String, Object> delParam = new HashMap<>();
        delParam.put("productId", product.getProductId());
        delParam.put("vendorId", product.getVendorId());
        pcrService.deleteSnapshotDetailByProductId(delParam);

        if (priceChangeRuleId == -1 || imPriceAlgorithmId == -1) {
            LOGGER.info("==Jian==No PriceChangeRule or no algorithm, so no product will be refreshed!");
        } else {
            SnapshotPriceDetail snapshotPriceDetail = new SnapshotPriceDetail();
            snapshotPriceDetail.setSnapshotPriceRuleId(snapshotPriceRuleId);
            snapshotPriceDetail.setProductId(product.getProductId());
            snapshotPriceDetail.setRetailPrice(product.getMaxRetailPrice());
            snapshotPriceDetail.setBoutiquePrice(boutiquePrice);
            snapshotPriceDetail.setImPrice(imPrice);
            snapshotPriceDetail.setBoutiqueDiscountOff(boutiqueDiscount.intValue());
            snapshotPriceDetail.setImDiscountOff(imDiscount.intValue());
            snapshotPriceDetail.setEnabled(true);
            if (param.get("rule_level") != null) {
                snapshotPriceDetail.setType(Byte.parseByte(param.get("rule_level").toString()));
            }
            pcrService.insertSnapshotPriceDetail(snapshotPriceDetail);
        }

        //refresh preview price
        IProductService productService = facilityService.getProductService();

        PriceChangeRule pcrPending = pcrService.selectByPrimaryKey(priceChangeRuleId);
        LOGGER.info("==Jian==[Pending] PriceChangeRule is {}", pcrPending);
        if (pcrPending != null && pcrPending.getPreviewStatus() == 1) {
            LOGGER.info("==Jian==The product is in the [pending] campaign scope!");
            //Job会清空preview price
            if (product.getMaxImPrice() != null && product.getMaxImPrice().compareTo(imPrice) == 1) {
                LOGGER.info("==Jian==The product preview price will be changed to {}!", imPrice);
                product.setPreviewImPrice(imPrice);
                productService.updateByPrimaryKey(product);
            }
        }
    }

    private Map<String, Object> setParam(Product product) {
        Map<String, Object> param = new HashMap<>();

        param.put("priceType", 1);
        param.put("vendorId", product.getVendorId());
        param.put("boutiqueId", product.getProductCode());
        param.put("seasonCode", product.getSeasonCode());
        param.put("categoryType", getCategoryType(product.getCategoryId()));
        param.put("productId", product.getProductId());
        param.put("brandId", product.getBrandId());
        param.put("categoryId", product.getCategoryId());

        return param;
    }

    private Map<String, Object> setDefaultDiscount() {
        Map<String, Object> map = new HashMap<>();
        IPriceChangeRuleService pcrService = facilityService.getPriceChangeRuleService();
        Long imDiscountDefault = Long.parseLong(pcrService.getSystemPropertyByName("IM_Discount_Default"));
        Long boutiqueDiscountDefault = Long.parseLong(pcrService.getSystemPropertyByName("Boutique_Discount_Default"));

        map.put("im_discount", imDiscountDefault);
        map.put("boutique_discount", boutiqueDiscountDefault);
        map.put("im_price_algorithm_id", -1L);
        map.put("price_change_rule_id", -1L);
        map.put("rule_level", -1);
        return map;
    }

    private void getPreBoutiqueDiscount(Map<String, Object> param, Map<String, Object> discountMap) {
        Integer isRuleFound = 0;
        IPriceChangeRuleService pcrService = facilityService.getPriceChangeRuleService();

        List<Map<String, Object>> productRuleList = pcrService.getProductRule(param);
        if (productRuleList != null && productRuleList.size() > 0) {
            isRuleFound = 1;
            if (productRuleList.size() > 1) {
                LOGGER.error("==Jian==productRuleList.size() 异常，productRuleList is {}", productRuleList.toString());
            }
        }

        List<Map<String, Object>> productGroupRuleList = new ArrayList<>();
        if (isRuleFound.equals(0)) {
            productGroupRuleList = pcrService.getProductGroupRule(param);
            if (productGroupRuleList != null && productGroupRuleList.size() > 0) {
                isRuleFound = 2;
                if (productRuleList.size() > 1) {
                    LOGGER.error("==Jian==productRuleList.size() 异常，productRuleList is {}", productRuleList.toString());
                }
            }
        }

        List<Map<String, Object>> prodCategoryBrandRule2List = new ArrayList<>();
        if (isRuleFound.equals(0)) {
            prodCategoryBrandRule2List = pcrService.getProdCategoryBrandRule2(param);
            if (prodCategoryBrandRule2List != null && prodCategoryBrandRule2List.size() > 0) {
                isRuleFound = 3;
                if (productRuleList.size() > 1) {
                    LOGGER.error("==Jian==prodCategoryBrandRule2List.size() 异常，prodCategoryBrandRule2List is {}", prodCategoryBrandRule2List.toString());
                }
            }
        }

        List<Map<String, Object>> prodCategoryBrandRule1List = new ArrayList<>();
        if (isRuleFound.equals(0)) {
            prodCategoryBrandRule1List = pcrService.getProdCategoryBrandRule1(param);
            if (prodCategoryBrandRule1List != null && prodCategoryBrandRule1List.size() > 0) {
                isRuleFound = 4;
                if (productRuleList.size() > 1) {
                    LOGGER.error("==Jian==prodCategoryBrandRule1List.size() 异常，prodCategoryBrandRule1List is {}", prodCategoryBrandRule1List.toString());
                }
            }
        }

        List<Map<String, Object>> prodCategoryBrandRule0List = new ArrayList<>();
        if (isRuleFound.equals(0)) {
            prodCategoryBrandRule0List = pcrService.getProdCategoryBrandRule0(param);
            if (prodCategoryBrandRule0List != null && prodCategoryBrandRule0List.size() > 0) {
                isRuleFound = 5;
                if (productRuleList.size() > 1) {
                    LOGGER.error("==Jian==prodCategoryBrandRule0List.size() 异常，prodCategoryBrandRule0List is {}", prodCategoryBrandRule0List.toString());
                }
            }
        }

        switch (isRuleFound) {
        case 1:
            discountMap.put("boutique_discount", productRuleList.get(0).get("discount_percentage").toString());
            discountMap.put("im_price_algorithm_id", productRuleList.get(0).get("im_price_algorithm_id").toString());
            discountMap.put("price_change_rule_id", productRuleList.get(0).get("price_change_rule_id").toString());
            discountMap.put("rule_level", 1);
            break;
        case 2:
            discountMap.put("boutique_discount", productGroupRuleList.get(0).get("discount_percentage").toString());
            discountMap.put("im_price_algorithm_id", productGroupRuleList.get(0).get("im_price_algorithm_id").toString());
            discountMap.put("price_change_rule_id", productGroupRuleList.get(0).get("price_change_rule_id").toString());
            discountMap.put("rule_level", 2);
            break;
        case 3:
            discountMap.put("boutique_discount", prodCategoryBrandRule2List.get(0).get("discount_percentage").toString());
            discountMap.put("im_price_algorithm_id", prodCategoryBrandRule2List.get(0).get("im_price_algorithm_id").toString());
            discountMap.put("price_change_rule_id", prodCategoryBrandRule2List.get(0).get("price_change_rule_id").toString());
            discountMap.put("rule_level", 3);
            break;
        case 4:
            discountMap.put("boutique_discount", prodCategoryBrandRule1List.get(0).get("discount_percentage").toString());
            discountMap.put("im_price_algorithm_id", prodCategoryBrandRule1List.get(0).get("im_price_algorithm_id").toString());
            discountMap.put("price_change_rule_id", prodCategoryBrandRule1List.get(0).get("price_change_rule_id").toString());
            discountMap.put("rule_level", 4);
            break;
        case 5:
            discountMap.put("boutique_discount", prodCategoryBrandRule0List.get(0).get("discount_percentage").toString());
            discountMap.put("im_price_algorithm_id", prodCategoryBrandRule0List.get(0).get("im_price_algorithm_id").toString());
            discountMap.put("price_change_rule_id", prodCategoryBrandRule0List.get(0).get("price_change_rule_id").toString());
            discountMap.put("rule_level", 5);
            break;
        }
    }

    private void getPreImDiscount(Product prd, Map<String, Object> discountParam) {
        IPriceRuleService priceRuleService = facilityService.getPriceRuleService();
        IPriceChangeRuleService priceChangeRuleService = facilityService.getPriceChangeRuleService();

        Long imPriceAlgorithmId = Long.parseLong(discountParam.get("im_price_algorithm_id").toString());

        Map<Long, Map<Integer, Integer>> brandDiscountMapping = priceRuleService.convertDiscountMapping(
                priceRuleService.getImBrandRuleMapping(imPriceAlgorithmId));
        Map<Long, Map<Integer, Integer>> hotBrandDiscountMapping = priceRuleService.convertDiscountMapping(priceRuleService.getHotImBrandRuleMapping());
        Long count = priceChangeRuleService.isHotBrandProduct(prd.getProductId());
        LOGGER.info("==Jian==count is {}", count);

        Integer imDiscount = null;
        if (count == 0) {
            if (brandDiscountMapping != null && !brandDiscountMapping.isEmpty()) {
                imDiscount = priceRuleService.getImDiscount(prd.getBrandId(), Long.parseLong(discountParam.get("boutique_discount").toString()),
                        brandDiscountMapping);
                LOGGER.info("==Jian==normal brand, imDiscount is {}", imDiscount);
            } else {
                LOGGER.info("==Jian==brandDiscountMapping is null !!");
            }

        } else {
            if (hotBrandDiscountMapping != null && !hotBrandDiscountMapping.isEmpty()) {
                imDiscount = priceRuleService.getImDiscount(prd.getBrandId(), Long.parseLong(discountParam.get("boutique_discount").toString()),
                        hotBrandDiscountMapping);
                LOGGER.info("==Jian==hotbrand, imDiscount is {}", imDiscount);
            } else {
                LOGGER.error("==Jian==hotBrandDiscountMapping is null !!");
            }
        }

        if (imDiscount != null) {
            discountParam.put("im_discount", imDiscount);
        }
    }

    private String getCategoryType(Long categoryId) {
        IPriceChangeRuleService pcrService = facilityService.getPriceChangeRuleService();
        Map<String, Object> param = new HashMap<>();
        param.put("categoryId", categoryId);
        try {
            List<Map<String, Object>> mapList = pcrService.getCategoryType(param);

            String c1 = StringUtils.trim(mapList.get(0).get("category_id").toString());

            if (c1.equals("1499") || c1.equals("1568")) {
                return "1";
            } else {
                return "2";
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.info("getCategoryType,Exception:" + e);
        }
        return null;
    }
}
